/*
    ******************************

    ******************************
*/

#include "redis.h"
#include <stdexcept> 

Redis::Redis(std::string h, int p) {
    // redis组件 依托hiredis
    spdlog::info("HTTP Server启用Redis, redis初始化!");
    this->host = "127.0.0.1";
    this->port = 6379;
    this->_connect = nullptr;
    this->_reply = nullptr;
}

Redis::~Redis() {
    spdlog::info("redis析构!");
    redisFree(_connect); //释放redisConnect()所产生的连接
    delete _connect;
    delete _reply;
}

void Redis::connect() {
    struct timeval timeout { 1, 500000 }; // 1.5 秒
    _connect = redisConnectWithTimeout(this->host.c_str(), this->port, timeout);
    if (_connect != nullptr && _connect->err) {
        spdlog::error("[redis] 连接失败: {} {}({})", _connect->errstr, __FILE__, __LINE__);
        logger->error("[redis] 连接失败: {} {}({})", _connect->errstr, __FILE__, __LINE__);
        throw std::runtime_error("[redis] 连接失败");
    }
}

std::string Redis::getValue(const std::string& key) {
    _reply = static_cast<redisReply*>(redisCommand(_connect, "GET %s", key.c_str()));

    // 处理redis执行错误的情况
    if(_reply == nullptr || _reply->type == REDIS_REPLY_ERROR) {
        logger->error("[redis] getValue {}执行失败:{}({})", key, __FILE__, __LINE__);
        throw std::runtime_error("[redis] get操作执行失败");
    }
    
    // 处理返回值为空
    if(_reply->type == REDIS_REPLY_NIL) {    
        throw REDIS_REPLY_NIL;
    }

    // 获取正常str
    std::string str = _reply->str;
    
    //释放redisCommand执行后返回的redisReply所占用的内存
    freeReplyObject(_reply);
    return str;
}

void Redis::set(std::string key, std::string value) {
    _reply = static_cast<redisReply*>(redisCommand(_connect, "SET %s %s", key.c_str(), value.c_str()));
    freeReplyObject(_reply);
}
